package com.itgacl.magic4j.libcommon.component.ws;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itgacl.magic4j.libcommon.component.cache.redis.RedisClient;
import com.itgacl.magic4j.libcommon.component.ws.cluster.Constants;
import com.itgacl.magic4j.libcommon.component.ws.cluster.bean.WebsocketMsg;
import com.itgacl.magic4j.libcommon.component.ws.cluster.mq.RocketMqSender;
import com.itgacl.magic4j.libcommon.util.IpUtil;

import com.itgacl.magic4j.libcommon.util.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;

/**
 * ws消息推送服务类
 */
@ConditionalOnProperty(prefix = "ws", value = "enable", havingValue = "true")
@Service
@Slf4j
public class WsService {

    @Autowired
    private RedisClient redisClient;

    @Value("${ws.cluster.type}")
    private String wsClusterType;

    /**
     * 发送文本消息
     * @param session
     * @param msg
     * @return
     * @throws IOException
     */
    public void sendMsg(WebSocketSession session, String msg) throws IOException {
        session.sendMessage(new TextMessage(msg));
    }

    /**
     * 发送消息
     * @param clientId
     * @param msg
     * @return
     * @throws IOException
     */
    public void sendMsg(String clientId, String msg) throws IOException {
        //对客户端发送消息的话使用session.getBasicRemote().sendText(XXX)
        WebSocketSession session = WsSessionManager.get(clientId);
        if(session!=null){
            log.debug("在本地服务器{}通过客户端ID{}找到了webSocket的Session{}，可以发送消息", IpUtil.getLocalIP(),clientId,session);
            session.sendMessage(new TextMessage(msg));
        }else {
            if(Constants.WS_CLUSTER_TYPE.REDIS.equals(wsClusterType)){
                //在本地服务器没有获取到webSocket的Session，通过redis广播消息到其他服务器
                log.debug("在本地服务器{}通过客户端ID{}没有找到了webSocket的Session，通过redis广播消息到其他服务器", IpUtil.getLocalIP(),clientId);
                sendRedisMsg(clientId,msg);
            }else {
                //在本地服务器没有获取到webSocket的Session，通过mq广播消息到其他服务器
                log.debug("在本地服务器{}通过客户端ID{}没有找到了webSocket的Session，通过mq广播消息到其他服务器", IpUtil.getLocalIP(),clientId);
                sendMqMsg(clientId,msg);
            }
        }
    }

    /**
     * 发送redis消息
     * @param clientId
     * @param msg
     */
    public void sendRedisMsg(String clientId, String msg){
        WebsocketMsg websocketMsg = new WebsocketMsg();
        websocketMsg.setMsgId(IdUtil.simpleUUID());
        websocketMsg.setSender(IpUtil.getLocalIP()+"-"+IdUtil.simpleUUID());
        websocketMsg.setContent(msg);
        websocketMsg.setReceiverId(clientId);
        String connServer = WsSessionManager.getConnServer(clientId);
        if(StrUtil.isNotBlank(connServer)){
            redisClient.sendMsg(connServer+Constants.TOPIC.WEBSOCKET_MSG_NOTIFY, JSON.toJSONString(websocketMsg));//广播消息到目标服务器
        }else {
            redisClient.sendMsg(Constants.TOPIC.WEBSOCKET_MSG_NOTIFY, JSON.toJSONString(websocketMsg));//广播消息
        }
    }

    /**
     * 发送MQ消息
     * @param clientId
     * @param msg
     */
    public void sendMqMsg(String clientId, String msg){
        WebsocketMsg websocketMsg = new WebsocketMsg();
        websocketMsg.setMsgId(IdUtil.simpleUUID());
        websocketMsg.setSender(IpUtil.getLocalIP()+"-"+IdUtil.simpleUUID());
        websocketMsg.setContent(msg);
        websocketMsg.setReceiverId(clientId);
        String connServer = WsSessionManager.getConnServer(clientId);
        RocketMqSender rocketMqSender = SpringContextUtils.getBean(RocketMqSender.class);
        if(rocketMqSender!=null){
            rocketMqSender.sendMessage(Constants.TOPIC.WEBSOCKET_MSG_NOTIFY, JSON.toJSONString(websocketMsg));//广播消息
        }
    }

    /**
     * 广播消息
     * @param msg
     * @return
     * @throws IOException
     */
    public void broadcastMsg(String msg) throws IOException {
        for (WebSocketSession session: WsSessionManager.webSocketSessionPool.values()) {
            session.sendMessage(new TextMessage(msg));
        }
    }
}
